package com.diy.sigmund.diycommon.test.controller.async;

import com.diy.sigmund.diycommon.entity.ResultMsg;
import com.diy.sigmund.diycommon.entity.base.exception.DiyRuntimeException;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

/**
 * @author ylm-sigmund
 * @since 2022/8/7 13:51
 */
@RestController
public class DeferredResultOrderTestController {


    private static final Logger log = LoggerFactory.getLogger(DeferredResultOrderTestController.class);

    private static volatile ConcurrentHashMap<String, DeferredResult<ResultMsg>> DEFERRED_RESULT = new ConcurrentHashMap<>(20000);
    private static volatile AtomicInteger ATOMIC_INTEGER = new AtomicInteger(0);

    // @PostConstruct
    // public void printRequestCount() {
    //     Executors.newSingleThreadScheduledExecutor()
    //             .scheduleAtFixedRate(() -> {
    //                 log.error("" + ATOMIC_INTEGER.get());
    //             }, 10, 1, TimeUnit.SECONDS);
    // }

    /**
     * <h1>控制器可以从不同的线程异步生成返回值——例如，响应外部事件（JMS 消息）、计划任务或其他事件。</h1>
     * <br>查询订单支付结果
     *
     * @param orderId 订单编号
     * @return DeferredResult
     */
    @GetMapping(value = "/common/queryOrderPayResult", produces = MediaType.APPLICATION_JSON_VALUE)
    public DeferredResult<ResultMsg> queryOrderPayResult(@RequestParam("orderId") String orderId) {
        log.info("订单orderId:[{}]发起了支付", orderId);
        ATOMIC_INTEGER.incrementAndGet();
        // 3s 超时
        DeferredResult<ResultMsg> result = new DeferredResult<>(3000L);
        // 超时操作
        result.onTimeout(() -> {
            DEFERRED_RESULT.get(orderId).setResult(ResultMsg.fail("超时了"));
            log.error("订单orderId:[{}]发起支付,获取结果超时了.", orderId);
        });

        // 完成操作
        result.onCompletion(() -> {
            log.info("订单orderId:[{}]完成.", orderId);
            DEFERRED_RESULT.remove(orderId);
        });

        // 保存此 DeferredResult 的结果
        DEFERRED_RESULT.put(orderId, result);
        return result;
    }

    /**
     * 支付回调
     *
     * @param orderId 订单id
     * @return 支付回调结果
     */
    @GetMapping(value = "/common/payNotify", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResultMsg payNotify(@RequestParam("orderId") String orderId) {
        log.info("订单orderId:[{}]支付完成回调", orderId);

        // 默认结果发生了异常
        if ("123".equals(orderId)) {
            DEFERRED_RESULT.get(orderId).setErrorResult(new DiyRuntimeException("订单发生了异常"));
            return ResultMsg.fail("回调处理失败");
        }

        if (DEFERRED_RESULT.containsKey(orderId)) {
            Optional.ofNullable(DEFERRED_RESULT.get(orderId)).ifPresent(result -> result.setResult(ResultMsg.success("完成支付")));
            // 设置之前orderId toPay请求的结果
            return ResultMsg.success("回调处理成功");
        }
        return ResultMsg.fail("回调处理失败");
    }

}
